change return type of pretty_deg_format to QString. (#896)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Sun, 31 Jul 2022 14:34:21 +0000 (08:34 -0600)
committerGitHub <noreply@github.com>
Sun, 31 Jul 2022 14:34:21 +0000 (08:34 -0600)
this fixes memory leak in garmin_gpi, and adds a test.
enhance testing of pretty_deg_format to get coverage of dms.

14 files changed:
defs.h
garmin_gpi.cc
garmin_txt.cc
html.cc
reference/garmin_gpi_position~gpx.gpi [new file with mode: 0644]
reference/pretty_degree.csv [new file with mode: 0644]
reference/pretty_degree0.csv [new file with mode: 0644]
reference/pretty_degree1.csv [new file with mode: 0644]
reference/pretty_degree2.csv [new file with mode: 0644]
testo.d/garmin_gpi.test
testo.d/unicsv.test
text.cc
unicsv.cc
util.cc

diff --git a/defs.h b/defs.h
index eed1a18f3b6985fa64e9f2647ebf8c5252705d66..e7888608392be142cd6a443076722d62313e9272 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -1085,7 +1085,7 @@ char* strip_html(const utf_string*);
 char* strip_nastyhtml(const QString& in);
 char* convert_human_date_format(const char* human_datef);      /* "MM,YYYY,DD" -> "%m,%Y,%d" */
 char* convert_human_time_format(const char* human_timef);      /* "HH+mm+ss"   -> "%H+%M+%S" */
-char* pretty_deg_format(double lat, double lon, char fmt, const char* sep, int html);    /* decimal ->  dd.dddd or dd mm.mmm or dd mm ss */
+QString pretty_deg_format(double lat, double lon, char fmt, const char* sep, bool html);    /* decimal ->  dd.dddd or dd mm.mmm or dd mm ss */
 
 QString get_filename(const QString& fname);                    /* extract the filename portion */
 
index f7a0c7cdcf7606972e784fb43063c745341563cc..450fcbd6d995c84ab671c4bb690769e238dd9567 100644 (file)
@@ -758,7 +758,7 @@ GarminGPIFormat::wdata_compute_size(writer_data_t* data) const
         str = wpt->notes;
       }
     } else if (opt_pos) {
-      str = pretty_deg_format(wpt->latitude, wpt->longitude, 's', " ", 0);
+      str = pretty_deg_format(wpt->latitude, wpt->longitude, 's', " ", false);
     }
 
 
index 06e1935f1b34f958348c2fed08f2a48d58a2b006..5928d595bc182a54bbb6288985623213013abe7f 100644 (file)
@@ -360,7 +360,7 @@ print_position(const Waypoint* wpt)
     *fout << "#####\n";
     fatal(MYNAME ": %s (%s) is outside of convertible area \"%s\"!\n",
           wpt->shortname.isEmpty() ? "Waypoint" : qPrintable(wpt->shortname),
-          pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, 0),
+          qPrintable(pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, false)),
           gt_get_mps_grid_longname(grid_index, MYNAME));
   }
 }
diff --git a/html.cc b/html.cc
index d46cc9f2e6ec4db67bbaa87ac58bb88d3552da2c..8f3c0773551c934b740b0650fded75236b944b1c 100644 (file)
--- a/html.cc
+++ b/html.cc
@@ -66,9 +66,9 @@ HtmlFormat::html_disp(const Waypoint* wpt) const
   gbfprintf(file_out, "\n<a name=\"%s\"><hr></a>\n", CSTR(wpt->shortname));
   gbfprintf(file_out, "<table width=\"100%%\">\n");
   gbfprintf(file_out, "<tr><td><p class=\"gpsbabelwaypoint\">%s - ",(global_opts.synthesize_shortnames) ? CSTR(mkshort_from_wpt(mkshort_handle, wpt)) : CSTR(wpt->shortname));
-  char* cout = pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", 1);
-  gbfprintf(file_out, "%s (%d%c %6.0f %7.0f)", cout, utmz, utmzc, utme, utmn);
-  xfree(cout);
+  gbfprintf(file_out, "%s (%d%c %6.0f %7.0f)",
+            CSTR(pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", true)),
+            utmz, utmzc, utme, utmn);
   if (wpt->altitude != unknown_alt) {
     gbfprintf(file_out, " alt:%d", (int)((altunits[0]=='f')?METERS_TO_FEET(wpt->altitude):wpt->altitude));
   }
@@ -161,11 +161,9 @@ HtmlFormat::html_disp(const Waypoint* wpt) const
         if (logpart) {
           double lat = xml_attribute(logpart->attributes, "lat").toDouble();
           double lon = xml_attribute(logpart->attributes, "lon").toDouble();
-          char* coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 1);
           gbfprintf(file_out,
                     "<span class=\"gpsbabellogcoords\">%s</span><br>\n",
-                    coordstr);
-          xfree(coordstr);
+                    CSTR(pretty_deg_format(lat, lon, degformat[2], " ", true)));
         }
 
         logpart = xml_findfirst(curlog, "groundspeak:text");
diff --git a/reference/garmin_gpi_position~gpx.gpi b/reference/garmin_gpi_position~gpx.gpi
new file mode 100644 (file)
index 0000000..7991d7c
Binary files /dev/null and b/reference/garmin_gpi_position~gpx.gpi differ
diff --git a/reference/pretty_degree.csv b/reference/pretty_degree.csv
new file mode 100644 (file)
index 0000000..d64d9aa
--- /dev/null
@@ -0,0 +1,9 @@
+lat|lon|desc
+0.134°S|0.135°W|point0
+0.134°N|0.135°E|point1
+1.134°S|1.135°W|point2
+1.134°N|1.135°E|point3
+10.134°S|10.135°W|point4
+10.134°N|10.135°E|point5
+80.134°S|100.135°W|point6
+80.134°N|100.135°E|point7
diff --git a/reference/pretty_degree0.csv b/reference/pretty_degree0.csv
new file mode 100644 (file)
index 0000000..03c62fd
--- /dev/null
@@ -0,0 +1,9 @@
+No,Latitude,Longitude,Name\r
+1,S0.13400,W0.13500,"point0"\r
+2,N0.13400,E0.13500,"point1"\r
+3,S1.13400,W1.13500,"point2"\r
+4,N1.13400,E1.13500,"point3"\r
+5,S10.13400,W10.13500,"point4"\r
+6,N10.13400,E10.13500,"point5"\r
+7,S80.13400,W100.13500,"point6"\r
+8,N80.13400,E100.13500,"point7"\r
diff --git a/reference/pretty_degree1.csv b/reference/pretty_degree1.csv
new file mode 100644 (file)
index 0000000..e6a41b4
--- /dev/null
@@ -0,0 +1,9 @@
+No,Latitude,Longitude,Name\r
+1,S0 08.040,W0 08.100,"point0"\r
+2,N0 08.040,E0 08.100,"point1"\r
+3,S1 08.040,W1 08.100,"point2"\r
+4,N1 08.040,E1 08.100,"point3"\r
+5,S10 08.040,W10 08.100,"point4"\r
+6,N10 08.040,E10 08.100,"point5"\r
+7,S80 08.040,W100 08.100,"point6"\r
+8,N80 08.040,E100 08.100,"point7"\r
diff --git a/reference/pretty_degree2.csv b/reference/pretty_degree2.csv
new file mode 100644 (file)
index 0000000..52c969e
--- /dev/null
@@ -0,0 +1,9 @@
+No,Latitude,Longitude,Name\r
+1,"S0 08'02.4""","W0 08'06.0""","point0"\r
+2,"N0 08'02.4""","E0 08'06.0""","point1"\r
+3,"S1 08'02.4""","W1 08'06.0""","point2"\r
+4,"N1 08'02.4""","E1 08'06.0""","point3"\r
+5,"S10 08'02.4""","W10 08'06.0""","point4"\r
+6,"N10 08'02.4""","E10 08'06.0""","point5"\r
+7,"S80 08'02.4""","W100 08'06.0""","point6"\r
+8,"N80 08'02.4""","E100 08'06.0""","point7"\r
index 15df6508e2e288040c7f52d3b5ed14b55b2adb6d..a58c3b1759bd0b2c9a2edb0d770cbdcea706cae1 100644 (file)
@@ -31,6 +31,10 @@ compare ${TMPDIR}/garmin_gpi_encoding.gpx ${TMPDIR}/garmin_gpi_encoding2.gpi.gpx
 gpsbabel -i gpx -f ${REFERENCE}/garmin_gpi.gpx -o garmin_gpi,category="Vinícolas",hide -F ${TMPDIR}/garmin_gpi_category~gpx.gpi
 compare ${REFERENCE}/garmin_gpi_category~gpx.gpi ${TMPDIR}/garmin_gpi_category~gpx.gpi
 
+# check position option 
+gpsbabel -i gpx -f ${REFERENCE}/garmin_gpi.gpx -o garmin_gpi,position -F ${TMPDIR}/garmin_gpi_position~gpx.gpi
+compare ${REFERENCE}/garmin_gpi_position~gpx.gpi ${TMPDIR}/garmin_gpi_position~gpx.gpi
+
 # check dual language read
 # spb_metro_norm.gpi from https://www.garmin.ru/download/extras/poi.php or  https://files.navicom.ru/spb_metro_norm.gpi
 gpsbabel -i garmin_gpi,languagecode=RU -f ${REFERENCE}/spb_metro_norm.gpi -o gpx -F ${TMPDIR}/spb_metro_norm_ru~gpi.gpx
index 63de3e97dd1b9d8ad7478df491deaa451cc74aa3..6c31bba9429e051f5198ef96bba189f893801edd 100644 (file)
@@ -46,3 +46,11 @@ gpsbabel -i unicsv -f ${REFERENCE}/humantodec1.csv -o gpx -F ${TMPDIR}/humantode
 compare ${REFERENCE}/humantodec.gpx ${TMPDIR}/humantodec1.gpx
 gpsbabel -i unicsv -f ${REFERENCE}/humantodec2.csv -o gpx -F ${TMPDIR}/humantodec2.gpx
 compare ${REFERENCE}/humantodec.gpx ${TMPDIR}/humantodec2.gpx
+
+# pretty degree format
+gpsbabel -i unicsv -f ${REFERENCE}/pretty_degree.csv -o unicsv,grid=0 -F ${TMPDIR}/pretty_degree0.csv
+compare ${REFERENCE}/pretty_degree0.csv ${TMPDIR}/pretty_degree0.csv
+gpsbabel -i unicsv -f ${REFERENCE}/pretty_degree.csv -o unicsv,grid=1 -F ${TMPDIR}/pretty_degree1.csv
+compare ${REFERENCE}/pretty_degree1.csv ${TMPDIR}/pretty_degree1.csv
+gpsbabel -i unicsv -f ${REFERENCE}/pretty_degree.csv -o unicsv,grid=2 -F ${TMPDIR}/pretty_degree2.csv
+compare ${REFERENCE}/pretty_degree2.csv ${TMPDIR}/pretty_degree2.csv
diff --git a/text.cc b/text.cc
index 9b5e478ca4a905a5d2e678e7396ca700d8289b31..313c379c078785702330a4edec2cf0e14f38b18d 100644 (file)
--- a/text.cc
+++ b/text.cc
@@ -77,18 +77,18 @@ TextFormat::text_disp(const Waypoint* wpt)
 
   GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
                            &utme, &utmn, &utmz, &utmzc);
-  char* tmpout1 = pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", 0);
   if (wpt->altitude != unknown_alt) {
     xasprintf(&altout, " alt:%d", (int)((altunits[0]=='f')?METERS_TO_FEET(wpt->altitude):wpt->altitude));
   } else {
     altout = (char*) "";
   }
-  xasprintf(&tmpout2, "%s (%d%c %6.0f %7.0f)%s", tmpout1, utmz, utmzc, utme, utmn, altout);
+  xasprintf(&tmpout2, "%s (%d%c %6.0f %7.0f)%s",
+            CSTR(pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", false)),
+            utmz, utmzc, utme, utmn, altout);
   gbfprintf(file_out, "%-16s  %59s\n",
             (global_opts.synthesize_shortnames) ? CSTR(mkshort_from_wpt(mkshort_handle, wpt)) : CSTR(wpt->shortname),
             tmpout2);
   xfree(tmpout2);
-  xfree(tmpout1);
   if (altout[0]) {
     xfree(altout);
   }
@@ -168,9 +168,8 @@ TextFormat::text_disp(const Waypoint* wpt)
         if (logpart) {
           double lat = xml_attribute(logpart->attributes, "lat").toDouble();
           double lon = xml_attribute(logpart->attributes, "lon").toDouble();
-          char* coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 0);
-          gbfprintf(file_out, "%s\n", coordstr);
-          xfree(coordstr);
+          gbfprintf(file_out, "%s\n",
+                    CSTR(pretty_deg_format(lat, lon, degformat[2], " ", false)));
         }
 
         logpart = xml_findfirst(curlog, "groundspeak:text");
index 6788f6dacbcda1b13fec6cf8c8e4668e79ff76cd..b88fc9a03cd54360fe18ca51b4de8f759199520c 100644 (file)
--- a/unicsv.cc
+++ b/unicsv.cc
@@ -1113,7 +1113,7 @@ UnicsvFormat::unicsv_fatal_outside(const Waypoint* wpt) const
   *fout << "#####\n";
   fatal(MYNAME ": %s (%s) is outside of convertible area of grid \"%s\"!\n",
         wpt->shortname.isEmpty() ? "Waypoint" : qPrintable(wpt->shortname),
-        pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, 0),
+        qPrintable(pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, false)),
         gt_get_mps_grid_longname(unicsv_grid_idx, MYNAME));
 }
 
@@ -1306,7 +1306,6 @@ void
 UnicsvFormat::unicsv_waypt_disp_cb(const Waypoint* wpt)
 {
   double lat, lon, alt;
-  char* cout = nullptr;
   const geocache_data* gc_data = nullptr;
   unicsv_waypt_ct++;
 
@@ -1327,22 +1326,19 @@ UnicsvFormat::unicsv_waypt_disp_cb(const Waypoint* wpt)
   switch (unicsv_grid_idx) {
 
   case grid_lat_lon_ddd:
-    cout = pretty_deg_format(lat, lon, 'd', unicsv_fieldsep, 0);
-    *fout << cout;
+    *fout << pretty_deg_format(lat, lon, 'd', unicsv_fieldsep, false);
     break;
 
   case grid_lat_lon_dmm:
-    cout = pretty_deg_format(lat, lon, 'm', unicsv_fieldsep, 0);
-    *fout << cout;
+    *fout << pretty_deg_format(lat, lon, 'm', unicsv_fieldsep, false);
     break;
 
   case grid_lat_lon_dms: {
-    cout = pretty_deg_format(lat, lon, 's', unicsv_fieldsep, 0);
-    char* sep = strchr(cout, ',');
-    *sep = '\0';
-    QString tmp = csv_enquote(cout, kUnicsvQuoteChar);
+    QString position = pretty_deg_format(lat, lon, 's', unicsv_fieldsep, false);
+    auto sep = position.indexOf(unicsv_fieldsep);
+    QString tmp = csv_enquote(position.left(sep), kUnicsvQuoteChar);
     *fout << tmp << unicsv_fieldsep;
-    tmp = csv_enquote(sep+1, kUnicsvQuoteChar);
+    tmp = csv_enquote(position.mid(sep+1), kUnicsvQuoteChar);
     *fout << tmp;
   }
   break;
@@ -1393,10 +1389,6 @@ UnicsvFormat::unicsv_waypt_disp_cb(const Waypoint* wpt)
     break;
   }
 
-  if (cout) {
-    xfree(cout);
-  }
-
   if FIELD_USED(fld_shortname) {
     unicsv_print_str(shortname);
   }
diff --git a/util.cc b/util.cc
index 981972daec6e72080ef6a6d59d65527bf299844c..362b680a9e642ce678159f1c10d6d2c43777222d 100644 (file)
--- a/util.cc
+++ b/util.cc
@@ -1123,10 +1123,10 @@ convert_human_time_format(const char* human_timef)
  * sep = string between lat and lon (separator)
  * html = 1 for html output otherwise text
  */
-char*
-pretty_deg_format(double lat, double lon, char fmt, const char* sep, int html)
+QString
+pretty_deg_format(double lat, double lon, char fmt, const char* sep, bool html)
 {
-  char*        result;
+  QString      result;
   char latsig = lat < 0 ? 'S':'N';
   char lonsig = lon < 0 ? 'W':'E';
   int latint = abs((int) lat);
@@ -1139,17 +1139,17 @@ pretty_deg_format(double lat, double lon, char fmt, const char* sep, int html)
     sep = " ";  /* default " " */
   }
   if (fmt == 'd') { /* ddd */
-    xasprintf(&result, "%c%6.5f%s%s%c%6.5f%s",
-              latsig, fabs(lat), html?"&deg;":"", sep,
-              lonsig, fabs(lon), html?"&deg;":"");
+    result = QStringLiteral("%1%2%3%4%5%6%7")
+             .arg(latsig).arg(fabs(lat), 6, 'f', 5).arg(html ? "&deg;" : "", sep)
+             .arg(lonsig).arg(fabs(lon), 6, 'f', 5).arg(html ? "&deg;" : "");
   } else if (fmt == 's') { /* dms */
-    xasprintf(&result, "%c%d%s%02d'%04.1f\"%s%c%d%s%02d'%04.1f\"",
-              latsig, latint, html?"&deg;":" ", (int)latmin, latsec, sep,
-              lonsig, lonint, html?"&deg;":" ", (int)lonmin, lonsec);
+    result = QStringLiteral("%1%2%3%4'%5\"%6%7%8%9%10'%11\"")
+             .arg(latsig).arg(latint).arg(html ? "&deg;" : " ").arg((int)latmin, 2, 10, QChar('0')).arg(latsec, 4, 'f', 1, QChar('0')).arg(sep)
+             .arg(lonsig).arg(lonint).arg(html ? "&deg;" : " ").arg((int)lonmin, 2, 10, QChar('0')).arg(lonsec, 4, 'f', 1, QChar('0'));
   } else { /* default dmm */
-    xasprintf(&result,  "%c%d%s%06.3f%s%c%d%s%06.3f",
-              latsig, latint, html?"&deg;":" ", latmin, sep,
-              lonsig, lonint, html?"&deg;":" ", lonmin);
+    result = QStringLiteral("%1%2%3%4%5%6%7%8%9")
+             .arg(latsig).arg(latint).arg(html ? "&deg;" : " ").arg(latmin, 6, 'f', 3, QChar('0')).arg(sep)
+             .arg(lonsig).arg(lonint).arg(html ? "&deg;" : " ").arg(lonmin, 6, 'f', 3, QChar('0'));
   }
   return result;
 }